/*
 * {comment of class}
 *
 * @author (C) <a href="http://www.carfield.com.hk">Carfield Yim</a>, 2004
 */
package hk.com.carfield.web.servlet;

import hk.com.carfield.core.Config;
import hk.com.carfield.util.FileObject;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;

public class Request extends hk.com.carfield.web.Request {
	private static final FileObject getFileObject(final FileItem fi) {
		return fi == null ? null : new FileObject() {
			public void delete() {
				fi.delete();
			}

			public String getName() {
				return fi.getName();
			}

			public void write(final File file) {
				try {
					fi.write(file);
				} catch (final Exception e) {
					throw new RuntimeException(e);
				}
			}
		};
	}

	public static final hk.com.carfield.web.Request getRequest(
			final HttpServletRequest req, final Config config) {
		final boolean isMultipart = FileUploadBase
				.isMultipartContent(new ServletRequestContext(req));
		final Map<String, FileObject> fileObjectMap = new HashMap<String, FileObject>();
		if (isMultipart) {
			final ServletFileUpload fu = new ServletFileUpload(
					new DiskFileItemFactory());
			try {
				final List<?> fileItems = fu.parseRequest(req);
				for (int i = 0; i < fileItems.size(); i++) {
					final FileItem fi = (FileItem) fileItems.get(i);
					fileObjectMap.put(fi.getFieldName(),
							Request.getFileObject(fi));
				}
			} catch (final FileUploadException e) {
				throw new RuntimeException(e);
			}
		}
		return new Request(config, req, fileObjectMap);
	}

	private final Map<String, FileObject> fileObjectMap;

	private final HttpServletRequest request;

	private final HttpSession session;

	private Request(final Config config, final HttpServletRequest req,
			final Map<String, FileObject> fileObjectMap) {
		super(config.getAdminPassword());
		request = req;
		this.fileObjectMap = fileObjectMap;
		session = req.getSession();
	}

	@Override
	public String clientIP() {
		return request.getRemoteAddr();
	}

	@Override
	public Collection<FileObject> getFileObject() {
		return fileObjectMap.values();
	}

	@Override
	public final String getParameter(final String name) {
		final String str = request.getParameter(name);
		return str == null ? "" : str;
	}

	@Override
	protected String getSessionValue(final String name) {
		return (String) session.getAttribute(name);
	}

	@Override
	public String host() {
		return request.getServerName();
	}

	@Override
	protected void setSessionValue(final String name, final String value) {
		session.setAttribute(name, value);
	}

	@Override
	public String toString() {
		final StringBuffer sb = new StringBuffer();
		try {
			request.setCharacterEncoding("UTF-8");
			sb.append("\nsuper.toString():\t").append(super.toString());
			sb.append("\nPath:\t").append(request.getRequestURI());
			sb.append("\nParameters:\t").append(request.getParameterMap());
			for (@SuppressWarnings("unchecked")
			final Enumeration<String> enumeration = request.getAttributeNames(); enumeration
					.hasMoreElements();) {
				final String element = enumeration.nextElement();
				sb.append(element).append(":\t")
						.append(request.getAttribute(element));
			}
		} catch (final UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
		return sb.toString();
	}
}